<!DOCTYPE html>
<html lang="en">
<head>
<style>
canvas {
    position: absolute;
    top: 0;
    left: 0;
    background-color:#CD5C5C;

}
</style>
    <title>birthday</title>
    <link rel="stylesheet" href="bootstrap-4.2.1-dist/css/bootstrap.css"/>
</head>
<body>
<div>
    <canvas id=c></canvas>
    <div class="container-fluid" style="position:absolute;margin-top: 100px">
<!--            <ul class="col bg-danger text-center" style="list-style: none">-->
<!--                <li><p>赣山鄱水启巍峨，</p></li>-->
<!--                <li><p>学府开新豫章旧郡于兹为盛。</p></li>-->
<!--                <li><p>杏岭瑶湖竞芬芳，</p></li>-->
<!--                <li><p>桃李绽放洪都新府傲娇中华。</p></li>-->
<!--            </ul>-->

        <ul class="m-auto col  text-center" style="list-style: none;font-size: 30px;color: #FFFFFF;font-family: 华文新魏,sans-serif">
            <li><p><img src="img/校庆.jpg" width="100" height="100"></p></li>
            <li><p>赣山苍苍，鄱水泱泱。</p></li>
            <li><p>大学巍巍，屹立西江。</p></li>
            <li><p>白鹿开先，杏岭为基。</p></li>
            <li><p>桃李芬芳，英才济济。</p></li>
            <li><p> 静思笃行，持中秉正。</p></li>
        </ul>
        </div>
</div>
<script>
var gl = c.getContext('webgl', {
        preserveDrawingBuffer: true
    }),
    w = c.width = window.innerWidth,
    h = c.height = window.innerHeight
, webgl = {}, opts = {
    projectileAlpha: .8,
    projectileLineWidth: 1.3,
    fireworkAngleSpan: .5,
    baseFireworkVel: 3,
    addedFireworkVel: 3,
    gravity: .03,
    lowVelBoundary: -.2,
    xFriction: .995,
    baseShardVel: 1,
    addedShardVel: .2,
    fireworks: 1000,
    baseShardsParFirework: 10,
    addedShardsParFirework: 10,
    shardFireworkVelMultiplier: .3,
    initHueMultiplier: 1 / 360,
    runHueAdder: .1 / 360
}

webgl.vertexShaderSource = `
uniform int u_mode;
uniform vec2 u_res;
attribute vec4 a_data;
varying vec4 v_color;

vec3 h2rgb( float h ){
	return clamp( abs( mod( h * 6. + vec3( 0, 4, 2 ), 6. ) - 3. ) -1., 0., 1. );
}
void clear(){
	gl_Position = vec4( a_data.xy, 0, 1 );
	v_color = vec4( 0, 0, 0, a_data.w );
}
void draw(){
	gl_Position = vec4( vec2( 1, -1 ) * ( ( a_data.xy / u_res ) * 2. - 1. ), 0, 1 );
	v_color = vec4( h2rgb( a_data.z ), a_data.w );
}
void main(){
	if( u_mode == 0 )
		draw();
	else
		clear();
}
`;
webgl.fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;

void main(){
	gl_FragColor = v_color;
}
`;

webgl.vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(webgl.vertexShader, webgl.vertexShaderSource);
gl.compileShader(webgl.vertexShader);

webgl.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(webgl.fragmentShader, webgl.fragmentShaderSource);
gl.compileShader(webgl.fragmentShader);

webgl.shaderProgram = gl.createProgram();
gl.attachShader(webgl.shaderProgram, webgl.vertexShader);
gl.attachShader(webgl.shaderProgram, webgl.fragmentShader);

gl.linkProgram(webgl.shaderProgram);
gl.useProgram(webgl.shaderProgram);

webgl.dataAttribLoc = gl.getAttribLocation(webgl.shaderProgram, 'a_data');
webgl.dataBuffer = gl.createBuffer();

gl.enableVertexAttribArray(webgl.dataAttribLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, webgl.dataBuffer);
gl.vertexAttribPointer(webgl.dataAttribLoc, 4, gl.FLOAT, false, 0, 0);

webgl.resUniformLoc = gl.getUniformLocation(webgl.shaderProgram, 'u_res');
webgl.modeUniformLoc = gl.getUniformLocation(webgl.shaderProgram, 'u_mode');

gl.viewport(0, 0, w, h);
gl.uniform2f(webgl.resUniformLoc, w, h);

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);

gl.lineWidth(opts.projectileLineWidth);

webgl.data = [];

webgl.clear = function() {

    gl.uniform1i(webgl.modeUniformLoc, 1);
    var a = .1;
    webgl.data = [-1, -1, 0, a,
        1, -1, 0, a, -1, 1, 0, a, -1, 1, 0, a,
        1, -1, 0, a,
        1, 1, 0, a
    ];
    webgl.draw(gl.TRIANGLES);
    gl.uniform1i(webgl.modeUniformLoc, 0);
    webgl.data.length = 0;
}
webgl.draw = function(glType) {

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(webgl.data), gl.STATIC_DRAW);
    gl.drawArrays(glType, 0, webgl.data.length / 4);
}

var fireworks = [],
    tick = 0,
    sins = [],
    coss = [],
    maxShardsParFirework = opts.baseShardsParFirework + opts.addedShardsParFirework,
    tau = 6.283185307179586476925286766559;

for (var i = 0; i < maxShardsParFirework; ++i) {
    sins[i] = Math.sin(tau * i / maxShardsParFirework);
    coss[i] = Math.cos(tau * i / maxShardsParFirework);
}

function Firework() {
    this.reset();
    this.shards = [];
    for (var i = 0; i < maxShardsParFirework; ++i)
        this.shards.push(new Shard(this));
}
Firework.prototype.reset = function() {

    var angle = -Math.PI / 2 + (Math.random() - .5) * opts.fireworkAngleSpan,
        vel = opts.baseFireworkVel + opts.addedFireworkVel * Math.random();

    this.mode = 0;
    this.vx = vel * Math.cos(angle);
    this.vy = vel * Math.sin(angle);

    this.x = Math.random() * w;
    this.y = h;

    this.hue = tick * opts.initHueMultiplier;

}
Firework.prototype.step = function() {

    if (this.mode === 0) {

        var ph = this.hue,
            px = this.x,
            py = this.y;

        this.hue += opts.runHueAdder;

        this.x += this.vx *= opts.xFriction;
        this.y += this.vy += opts.gravity;

        webgl.data.push(
            px, py, ph, opts.projectileAlpha * .2,
            this.x, this.y, this.hue, opts.projectileAlpha * .2);

        if (this.vy >= opts.lowVelBoundary) {
            this.mode = 1;

            this.shardAmount = opts.baseShardsParFirework + opts.addedShardsParFirework * Math.random() | 0;

            var baseAngle = Math.random() * tau,
                x = Math.cos(baseAngle),
                y = Math.sin(baseAngle),
                sin = sins[this.shardAmount],
                cos = coss[this.shardAmount];

            for (var i = 0; i < this.shardAmount; ++i) {

                var vel = opts.baseShardVel + opts.addedShardVel * Math.random();
                this.shards[i].reset(x * vel, y * vel)
                var X = x;
                x = x * cos - y * sin;
                y = y * cos + X * sin;
            }
        }

    } else if (this.mode === 1) {

        this.ph = this.hue
        this.hue += opts.runHueAdder;

        var allDead = true;
        for (var i = 0; i < this.shardAmount; ++i) {
            var shard = this.shards[i];
            if (!shard.dead) {
                shard.step();
                allDead = false;
            }
        }

        if (allDead)
            this.reset();
    }

}

function Shard(parent) {
    this.parent = parent;
}
Shard.prototype.reset = function(vx, vy) {
    this.x = this.parent.x;
    this.y = this.parent.y;
    this.vx = this.parent.vx * opts.shardFireworkVelMultiplier + vx;
    this.vy = this.parent.vy * opts.shardFireworkVelMultiplier + vy;
    this.starty = this.y;
    this.dead = false;
    this.tick = 1;
}
Shard.prototype.step = function() {

    this.tick += .05;

    var px = this.x,
        py = this.y;

    this.x += this.vx *= opts.xFriction;
    this.y += this.vy += opts.gravity;

    var proportion = 1 - (this.y - this.starty) / (h - this.starty);

    webgl.data.push(
        px, py, this.parent.ph, opts.projectileAlpha / this.tick,
        this.x, this.y, this.parent.hue, opts.projectileAlpha / this.tick);

    if (this.y > h)
        this.dead = true;
}

function anim() {

    window.requestAnimationFrame(anim)

    webgl.clear();

    ++tick;

    if (fireworks.length < opts.fireworks)
        fireworks.push(new Firework);

    fireworks.map(function(firework) {
        firework.step();
    });

    webgl.draw(gl.LINES);
}
anim();

window.addEventListener('resize', function() {

    w = c.width = window.innerWidth;
    h = c.height = window.innerHeight;

    gl.viewport(0, 0, w, h);
    gl.uniform2f(webgl.resUniformLoc, w, h);
})
window.addEventListener('click', function(e) {
    var firework = new Firework();
    firework.x = e.clientX;
    firework.y = e.clientY;
    firework.vx = 0;
    firework.vy = 0;
    fireworks.push(firework);
});
</script>
</body>
</html>